namespace Warehouse

open System.Collections.ObjectModel
open System
open FSharp.Windows

type OfferController(?repository) = 
    inherit Controller<OfferEvents, OfferModel>()

    let repository = defaultArg repository (new DataModel.Repository())

    override this.InitModel model = 
        model.ClientLookUp <- repository.Clients
        model.Items <- ObservableCollection()
        model.UpcNoteLookUp <- repository.UpcNotes

    override this.Dispatcher = function
        | SelectedClientChanged -> Sync this.LoadClientData
        | SelectedBrandChanged -> Sync this.LoadBrandData
        | New -> Sync this.New 
        | Save -> Sync this.Save
        | Print -> Sync this.Print
        | IncludeAllProductsToggle on -> Sync(this.IncludeAllProducts on)
        | RegularSizeCommissionForBrandChanged -> Sync this.RegularSizeCommissionForBrandChanged 
        | LitrSizeCommissionForBrandChanged -> Sync this.LitrSizeCommissionForBrandChanged 

    member this.LoadClientData model = 
        model.Items <- model.SelectedClient.Offers |> Seq.map EntityModel.Load |> ObservableCollection.ofSeq

    member this.LoadBrandData model = 
        let byBrand = model.SelectedOffer.SelectedBrand
        if box byBrand <> null && byBrand.Products = null
        then
            byBrand.Products <- this.ByProductModels(byBrand.Brand, model.SelectedClient.Id)
            for byProduct in byBrand.Products do
                byProduct.Commission <- if byProduct.IsLitrSize then byBrand.LitrSizePct else byBrand.RegularPct

    member this.ByProductModels(brand : DataModel.Brand, clientId) = 
        [|
            for p in brand.Products() do
                let availableForOffer = repository.ProductOfferAvailableQuantity p
                if availableForOffer > 0 
                then
                    let byProduct : OfferByProductModel = Model.Create()
                    byProduct.Product <- p
                    byProduct.Commission <- p.ClientCommission clientId 
                    byProduct.Quantity <- availableForOffer
                    byProduct.Compute()
                    yield byProduct
        |]
        
    member this.New model = 
        model |> Validation.objectRequired <@ fun m -> m.SelectedClient @>

        if model.IsValid 
        then
            let clientId = model.SelectedClient.Id
            let offer : OfferDetailsModel = Model.Create()
            offer.Date <- DateTime.Today
            offer.ByBrand <- ObservableCollection
                [|
                    for brand in repository.Brands do
                        let byBrand : OfferByBrandModel = Model.Create()
                        byBrand.Brand <- brand
                        let regular, litrSize = brand.ClientCommission clientId
                        byBrand.RegularPct <- regular
                        byBrand.LitrSizePct <- litrSize
                        yield byBrand
                |]

            model.Items.Add offer
            model.SelectedOffer <- offer

    member this.IncludeAllProducts on model = 
        let byBrand = model.SelectedOffer.SelectedBrand
        for byProduct in byBrand.Products do
            byProduct.Include <- on

    member this.Save model = 
        assert model.SelectedOffer.IsNewEntity
        let offer =  model.SelectedOffer
        offer.UpdateEntity()
        offer.Entity.Client <- model.SelectedClient
        for brandOffer in model.SelectedOffer.ByBrand do
            if brandOffer.Products <> null then
                for product in brandOffer.Products do
                    if product.Include then 
                        product.UpdateEntity()
                        product.Entity.Offer <- offer.Entity

        offer.SaveEntity repository
        offer.Id <- offer.Entity.Id
        model.SelectedOffer <- model.SelectedOffer

    member this.Print model = 
        ReportForm.ShowReportDialog(
            reportName = "Offer", 
            parameters = ["offerId", string model.SelectedOffer.Id]
        )

    member this.RegularSizeCommissionForBrandChanged model = 
        let brand = model.SelectedOffer.SelectedBrand
        for product in brand.Products do
            if not product.IsLitrSize 
            then
                product.Commission <- brand.RegularPct

    member this.LitrSizeCommissionForBrandChanged model = 
        let brand = model.SelectedOffer.SelectedBrand
        for product in brand.Products do
            if product.IsLitrSize 
            then
                product.Commission <- brand.LitrSizePct
